package com.wonder.common.utils.file;

import java.io.*;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import javax.servlet.http.HttpServletRequest;

import cn.hutool.core.map.multi.Table;
import com.wonder.common.utils.StringUtils;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItem;
import org.apache.commons.io.IOUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;


/**
 * 文件处理工具类
 * 
 * @author Wonder
 */
public class FileUtils extends org.apache.commons.io.FileUtils
{
    public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+";
    // 密码提花
 	private static final char[] hexCode = "0123456789ABCDEF".toCharArray();

    /**
     * 输出指定文件的byte数组
     * 
     * @param filePath 文件路径
     * @param os 输出流
     * @return
     */
    public static void writeBytes(String filePath, OutputStream os) throws IOException
    {
        FileInputStream fis = null;
        try
        {
            File file = new File(filePath);
            if (!file.exists())
            {
                throw new FileNotFoundException(filePath);
            }
            fis = new FileInputStream(file);
            byte[] b = new byte[1024];
            int length;
            while ((length = fis.read(b)) > 0)
            {
                os.write(b, 0, length);
            }
        }
        catch (IOException e)
        {
            throw e;
        }
        finally
        {
            if (os != null)
            {
                try
                {
                    os.close();
                }
                catch (IOException e1)
                {
                    e1.printStackTrace();
                }
            }
            if (fis != null)
            {
                try
                {
                    fis.close();
                }
                catch (IOException e1)
                {
                    e1.printStackTrace();
                }
            }
        }
    }

    /**
     * 删除文件
     * 
     * @param filePath 文件
     * @return
     */
    public static boolean deleteFile(String filePath)
    {
        boolean flag = false;
        File file = new File(filePath);
        // 路径为文件且不为空则进行删除
        if (file.isFile() && file.exists())
        {
            file.delete();
            flag = true;
        }
        return flag;
    }

    /**
     * 文件名称验证
     * 
     * @param filename 文件名称
     * @return true 正常 false 非法
     */
    public static boolean isValidFilename(String filename)
    {
        return filename.matches(FILENAME_PATTERN);
    }

    /**
     * 下载文件名重新编码
     * 
     * @param request 请求对象
     * @param fileName 文件名
     * @return 编码后的文件名
     */
    public static String setFileDownloadHeader(HttpServletRequest request, String fileName)
            throws UnsupportedEncodingException
    {
        final String agent = request.getHeader("USER-AGENT");
        String filename = fileName;
        if (agent.contains("MSIE"))
        {
            // IE浏览器
            filename = URLEncoder.encode(filename, "utf-8");
            filename = filename.replace("+", " ");
        }
        else if (agent.contains("Firefox"))
        {
            // 火狐浏览器
            filename = new String(fileName.getBytes(), "ISO8859-1");
        }
        else if (agent.contains("Chrome"))
        {
            // google浏览器
            filename = URLEncoder.encode(filename, "utf-8");
        }
        else
        {
            // 其它浏览器
            filename = URLEncoder.encode(filename, "utf-8");
        }
        return filename;
    }
    
    /**
     * 获取上传文件的md5
     * @param file
     * @return
     * @throws Exception 
     * @throws IOException
     */
    public static String getMd5(MultipartFile file) throws Exception {
        try {
            //获取文件的byte信息
            byte[] uploadBytes = file.getBytes();
            // 拿到一个MD5转换器
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            byte[] digest = md5.digest(uploadBytes);
            //转换为16进制
            return new BigInteger(1, digest).toString(16);
        } catch (Exception e) {
        	 throw e;
        }
    }

 // 文件类取MD5
    public static String calcMD5(File file){
        try (InputStream stream = Files.newInputStream(file.toPath(), StandardOpenOption.READ)) {
            return calcMD5(stream);
        }catch (IOException e) {
            e.printStackTrace();
            return "";
        }
    }
    // 输入流取MD5
    public static String calcMD5(InputStream stream) {
        try {
            MessageDigest digest = MessageDigest.getInstance("MD5");
            byte[] buf = new byte[8192];
            int len;
            while ((len = stream.read(buf)) > 0) {
                digest.update(buf, 0, len);
            }
            return toHexString(digest.digest());
        } catch (IOException e) {
            e.printStackTrace();
            return "";
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return "";
        }
    }
 
    public static String toHexString(byte[] data) {
        StringBuilder r = new StringBuilder(data.length * 2);
        for (byte b : data) {
            r.append(hexCode[(b >> 4) & 0xF]);
            r.append(hexCode[(b & 0xF)]);
        }
        return r.toString();
    }

    /**
     * 网络地址转换成二进制数组
     * @return
     */
    public static byte[] getFileStream(String url){
        byte[] btImg = null;
        try {
            URL httpUrl = new URL(url);
            HttpURLConnection connection = (HttpURLConnection) httpUrl.openConnection();
//           connection.setRequestMethod("GET");
//           connection.setConnectTimeout(5 * 1000);
//           connection.setRequestProperty("User-Agent", "Mozilla/5.0");
            InputStream inStream = connection.getInputStream();//通过输入流获取图片数据
            btImg = readInputStream(inStream);//得到二进制数据
            return btImg;
        } catch (Exception e){
            e.printStackTrace();
            System.out.println(e.getMessage());
        }
        return null;
    }


    /**
     * 从输入流中获取数据
     * @param inStream 输入流
     * @return
     * @throws Exception
     */
    public static byte[] readInputStream(InputStream inStream) throws Exception{
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len = 0;
        while( (len=inStream.read(buffer)) != -1 ){
            outStream.write(buffer, 0, len);
        }
        inStream.close();
        outStream.close();
        return outStream.toByteArray();

    }

    /**
     * byte 转换为 MultipartFile
     * @param bytes
     * @return
     */
    public static MultipartFile encodeToMultipartFile(byte [] bytes) {
        MultipartFile multipartFile = null;
        InputStream input = null;
        OutputStream outputStream = null;
        File tempFile = null;
        try {
            String path = "";
            String os = System.getProperty("os.name");
            if(os.toLowerCase().startsWith("win")){
                path = "D:" + File.separator + "file" + File.separator;
            } else {
                path = "/home/temp" + File.separator + "file" + File.separator;
            }

            File file = new File(path);
            file.mkdirs();
            path = path + System.currentTimeMillis() + ".jpg";
            tempFile = new File(path);
            tempFile.createNewFile();

            // 把 byte 转换为 File 文件
            FileUtils.getFileByBytes(bytes, path);

            // 第一个参数 fieldName 就是文件上传的 name, 这里我写的是 uploadFile
            FileItem fileItem = new DiskFileItem("uploadFile", Files.probeContentType(tempFile.toPath()), false, tempFile.getName(), (int) tempFile.length(), tempFile.getParentFile());
            input = new FileInputStream(tempFile);
            outputStream = fileItem.getOutputStream();
            IOUtils.copy(input, outputStream);

            multipartFile = new CommonsMultipartFile(fileItem);


        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                input.close();
                outputStream.close();
            } catch (Exception e) {
                e.printStackTrace();
            }

        }

        // 删除这个 File
        if (tempFile.exists()) {
            tempFile.delete();
        }

        return multipartFile;
    }
    /**
     * byte [] 转换为 File
     * @param bytes
     * @param filePath
     */
    public static void getFileByBytes(byte[] bytes, String filePath) {
        BufferedOutputStream bos = null;
        FileOutputStream fos = null;
        File file = null;
        try {
            File dir = new File(filePath);
            // 判断文件目录是否存在
            if (!dir.exists() && dir.isDirectory()) {
                dir.mkdirs();
            }
            file = new File(filePath);

            //输出流
            fos = new FileOutputStream(file);

            //缓冲流
            bos = new BufferedOutputStream(fos);

            //将字节数组写出
            bos.write(bytes);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    public static String getCellValue(Cell cell) {

        if (cell == null) {
            return "";
        }

        if ("NUMERIC".equals(cell.getCellType().name())) {
            return new BigDecimal(cell.getNumericCellValue()).toString();
        } else if ("STRING".equals(cell.getCellType().name()))
            return StringUtils.trimToEmpty(cell.getStringCellValue());
        else if ("FORMULA".equals(cell.getCellType().name())) {
            return StringUtils.trimToEmpty(cell.getCellFormula());
        } else if ("BLANK".equals(cell.getCellType().name())) {
            return "";
        } else if ("BOOLEAN".equals(cell.getCellType().name())) {
            return String.valueOf(cell.getBooleanCellValue());
        } else if ("ERROR".equals(cell.getCellType().name())) {
            return "ERROR";
        } else {
            return cell.toString().trim();
        }
    }


}

